package ch.elca.lol.puissance4.player.net;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import ch.elca.lol.puissance4.board.Board;
import ch.elca.lol.puissance4.util.Util;

// TODO: manage exceptions in Networker, can we make it work without requiring that client and server have different tokens ?
class Networker {
	private final int PORT = 6666;
	
	private String name;
	
	private Socket connection;
	private InputStream input;
	private OutputStream output;
	
	protected Networker(boolean server) {
		try {
			if(server)
				setupServer();
			else
				setupClient();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	private void setupServer() throws IOException {
		this.name = "Server";
		
		ServerSocket ssocket = new ServerSocket(PORT);
		log("waiting for incoming connection on " + PORT + ".");
		connection = ssocket.accept();
		
		input = connection.getInputStream();
		output = connection.getOutputStream();
	}
	
	private void setupClient() throws IOException {
		this.name = "Client";
		
		System.out.print("Client: please enter the host to connect to: ");
		String host = Util.stdinNextLine();
		InetAddress address = InetAddress.getByName(host);
		
		log("trying to connect on host " + address + ":" + PORT);
		connection = new Socket(address, PORT);
		input = connection.getInputStream();
		output = connection.getOutputStream();
		log("connection established");
	}
	
	private boolean verbose = true;
	
	protected void log(String msg) {
		if(verbose) {
			System.out.println(name + ": " + msg);
		}
	}
	
	protected int readInt() {
		try {
			return input.read();
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		return -1;
	}
	
	protected void writeInt(int col) {
		try {
			output.write(col);
			output.flush();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	protected void close() {
		try {
			connection.close();
			input.close();
			output.close();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	public int play(Board b) {
		log("waiting for incoming move.");
		int res = readInt();
		return res;
	}
	
	public void played(int col) {
		log("sending move.");
		writeInt(col);
	}
	
	public String toString() {
		return this.getClass().getSimpleName();
	}
}
